package com.xbongbong.saas.help;

/**
 * @author: 汪腾伟
 * @date: Created in 2021/11/30 10:38
 * @description：
 */

import com.xbongbong.paas.domain.entity.ext.ConditionsEntityExt;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.manager.feign.AliyuncallCenterFeignClient;
import com.xbongbong.paas.pojo.dto.AliyunCallCenterListDTO;
import com.xbongbong.paas.pojo.dto.CallCallLogListDTO;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.service.CallCenterCallLogService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.pro.detailtab.dto.DetailCommunicateDTO;
import com.xbongbong.pro.detailtab.dto.DetailTabDataGetDTO;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.ClueUserEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.enums.CallCenterCallLogCallSourceEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.CustomerCommunicateEnum;
import com.xbongbong.saas.model.ClueUserModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.service.toolbox.help.UserTeamHelp;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.enums.DataPermissionEnum;
import com.xbongbong.sys.model.UserModel;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author: 汪腾伟
 * @date: Created in 2021/11/29 16:57
 * @description： 详情界面的tab栏的数据权限帮助类
 */
@Slf4j
@Component
public class DetailTabDataPermissionHelp {
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private ClueUserModel clueUserModel;
    @Resource
    private UserModel userModel;
    @Resource
    private AliyuncallCenterFeignClient aliyuncallCenterFeignClient;
    @Resource
    private CallCenterCallLogService callCenterCallLogService;
    @Resource
    private UserTeamHelp userTeamHelp;

    /**
     * 详情里面tab栏里面的数据权限的过滤（前置条件是要当前表单-》表单设置-》团队成员-》数据隔离）,分以下两种情况
     *   （1）如果数据权限是超管、老板以及数据权限是全公司，那么详情tab不需要过滤
     *   （2）非以上的这种情况，这时候要求当前登录人不仅满足数据权限并且要在数据的团队里面
     *
     * @param detailTabDataGetDTO 详情接受实体
     */
    public void detailTabPermission(DetailTabDataGetDTO detailTabDataGetDTO, Integer linkBusinessType) throws XbbException {
        List<ConditionsEntityExt> conditionsEntityExts = detailTabPermissionConditions(detailTabDataGetDTO.getCorpid(), detailTabDataGetDTO.getFormId(), detailTabDataGetDTO.getBusinessType(), linkBusinessType, detailTabDataGetDTO.getLoginUser());
        detailTabDataGetDTO.setPermissionConditions(conditionsEntityExts);
    }

    public List<ConditionsEntityExt> detailTabPermissionConditions(String corpid, Long formId, Integer businessType, Integer linkBusinessType, UserVO userVO) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, formId, businessType);
        List<ConditionsEntityExt> conditions = new ArrayList<>();
        //获取当前业务的最大数据权限
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, linkBusinessType, 0L);
        if (userVO.isAdminOrBoss()
                || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission))
                || formShareTag) {
            return conditions;
        }
        List<String> sysDataPermissionUserList = getSysDataPermissionUserList(userVO, dataPermission);
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(FieldTypeEnum.TEAM_USER.getAlias());
        conditionsEntityExt.setFieldType(FieldTypeEnum.TEAM_USER.getType());
        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
        conditionsEntityExt.setValue(new ArrayList<>(new ArrayList<>(sysDataPermissionUserList)));
        conditions.add(conditionsEntityExt);
        return conditions;
    }

    /**
     * 这个方法的本质思路跟detailTabPermission方法一致，但是重新拆出来的原因是因为，业务只有负责人，没有负责人团队。并且这个负责人是存主表的owner_id字段中
     *
     * @param detailTabDataGetDTO
     *
     * @return
     */
    public List<ConditionsEntityExt> detailTabNoTeamPermission(DetailTabDataGetDTO detailTabDataGetDTO, Integer linkBusinessType) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(detailTabDataGetDTO.getCorpid(), detailTabDataGetDTO.getFormId(), detailTabDataGetDTO.getBusinessType());
        List<ConditionsEntityExt> conditions = new ArrayList<>();
        UserEntity userEntity = new UserEntity();
        UserVO userVO = detailTabDataGetDTO.getLoginUser();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, linkBusinessType, 0L);
        if (userVO.isAdminOrBoss()
                || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission))
                || formShareTag) {
            return conditions;
        }
        List<String> sysDataPermissionUserList = getSysDataPermissionUserList(userVO, dataPermission);
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setAttr(FieldTypeEnum.OWNERID.getAlias());
        conditionsEntityExt.setFieldType(FieldTypeEnum.OWNERID.getType());
        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
        conditionsEntityExt.setValue(new ArrayList<>(sysDataPermissionUserList));
        conditions.add(conditionsEntityExt);
        return conditions;
    }

    /**
     * 获取详情页线索列表
     *
     * @param boolQueryBuilder
     * @param corpid
     * @param formId
     * @param businessType
     * @param linkBusinessType
     * @param userVO
     */
    public List<String> detailTeamBoolQueryParamPermission(BoolQueryBuilder boolQueryBuilder, String corpid, Long formId, Integer businessType, Integer linkBusinessType, UserVO userVO,
                                          IndexTypeEnum indexTypeEnum) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, formId, businessType);
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, linkBusinessType, 0L);
        if (userVO.isAdminOrBoss()
                || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission))
                || formShareTag) {
            return new ArrayList<>();
        }
        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ONE,false);

        return userIdIn;
    }

    /**
     * 客户、线索详情页的跟进记录的数据权限的过滤,满足以下条件之一可见
     *    （1） 成员属于跟进记录创建人
     *    （2） 成员拥有跟进记录的数据可见权限
     *    （3） 成员与跟进记录的创建人属于同一个协作团队||数据符合当前成员的共享规则
     *    所以总的原则就是需要把符合条件的人都查出来
     * 其他业务详情页的跟进记录数据权限过滤，满足以下条件之一可见
     *    (1) 成员属于跟进记录创建人
     *    (2) 成员拥有跟进记录的数据可见权限
     *
     * 特殊：访客计划因为都没有协同人字段，所以这边不能设置共享和隔离，所以访客计划默认都是共享模式
     *
     * @param detailCommunicateDTO
     */
    public List<ConditionsEntityExt> detailCustomerCommunicateDataFilter(DetailCommunicateDTO detailCommunicateDTO, BoolQueryBuilder boolQueryBuilder, Integer linkBusinessType) throws XbbException {
        String corpid = detailCommunicateDTO.getCorpid();
        Integer businessType = detailCommunicateDTO.getParentBusinessType();
        Long dataId = detailCommunicateDTO.getParentId();
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, detailCommunicateDTO.getFormId(), businessType);
        UserVO userVO = detailCommunicateDTO.getLoginUser();
        String userId = userVO.getUserId();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, linkBusinessType, 0L);
        if (userVO.isAdminOrBoss() || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission)) || formShareTag) {
            return new ArrayList<>();
        }
        //下面就代表是隔离模式
        //----------------拼装团队数据权限--------------------
        List<String> finalUserIdList = new ArrayList<>();
        //这部门是我们角色权限的人
        List<String> sysDataPermissionUserList = getSysDataPermissionUserList(userVO, dataPermission);
        if (CollectionsUtil.isNotEmpty(sysDataPermissionUserList)) {
            finalUserIdList.addAll(sysDataPermissionUserList);
        }
        //这部门是团队里面的人
        Map<String,Object> param = new HashMap<>();
        param.put("corpid", corpid);
        param.put("dataId", dataId);
        param.put("del", BasicConstant.ZERO);
        if (Objects.equals(businessType, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode())) {
            List<CustomerUserEntity> customerUserEntityList = customerUserModel.findEntitys(param);
            List<String>  userIdStrList = getCustomerUserIdList(customerUserEntityList, userId);
            if (CollectionsUtil.isNotEmpty(userIdStrList)) {
                finalUserIdList.addAll(userIdStrList);
            }
        } else if (Objects.equals(businessType,XbbRefTypeEnum.CLUE.getCode())) {
            List<ClueUserEntity> clueUserEntities = clueUserModel.findEntitys(param);
            List<String>  userIdStrList = getClueUserIdList(clueUserEntities, userId);
            if (CollectionsUtil.isNotEmpty(userIdStrList)) {
                finalUserIdList.addAll(userIdStrList);
            }
        }

        List<ConditionsEntityExt> conditionsEntityExts = new ArrayList<>();
        ConditionsEntityExt conditionsEntityExt = new ConditionsEntityExt();
        conditionsEntityExt.setSymbol(ConditionEnum.IN.getSymbol());
        conditionsEntityExt.setValue(new ArrayList<>(finalUserIdList));
        conditionsEntityExt.setAttr(FieldTypeEnum.CREATORID.getAlias());
        conditionsEntityExt.setFieldType(FieldTypeEnum.CREATORID.getType());
        conditionsEntityExts.add(conditionsEntityExt);
        return conditionsEntityExts;
    }

    /**
     * 详情页通话记录数据权限过滤
     * （1）如果是云呼超管和老呼叫中心超管，就查询全部
     * （2）如果是云呼超管和老呼叫中心非超管，就需要call_source和user_id作为查询条件
     *  (3)如果是云呼非超管和老呼叫中心超管，就需要call_source和user_id作为查询条件
     *  (4)如果两个都是非超管，只需要user_id作为查询条件
     *
     * @param boolQueryBuilder
     * @param callCallLogListDTO
     * @param isActiveAliyunCall 是否有云呼的数据权限
     */
    public void detailTabCallLogDataFilter(BoolQueryBuilder boolQueryBuilder, CallCallLogListDTO callCallLogListDTO, boolean isActiveAliyunCall) throws XbbException {
        String corpid = callCallLogListDTO.getCorpid();
        Integer businessType = callCallLogListDTO.getBusinessType();
        Integer dataId = callCallLogListDTO.getDataId();
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, callCallLogListDTO.getFormId(), businessType);
        UserVO userVO = callCallLogListDTO.getLoginUser();
        String userId = userVO.getUserId();
        if (formShareTag) {
            return;
        }
        //下面代表是隔离模式
        //代表阿里云呼超管权限
        boolean aliyunCallAdminPer = false;
        List<String> aliyunCallUserList = new ArrayList<>();
        //代表呼叫中心超管权限
        boolean callAdminPer = false;
        //这部分是数据权限的人，云呼数据权限 + 老呼叫中心数据权限
        //云呼的数据权限
        if (isActiveAliyunCall) {
            //只有有云呼才去做一层查询
            AliyunCallCenterListDTO aliyunCallCenterListDTO = new AliyunCallCenterListDTO();
            aliyunCallCenterListDTO.setUserId(userId);
            aliyunCallCenterListDTO.setCorpid(corpid);
            aliyunCallCenterListDTO.setPlatform(callCallLogListDTO.getPlatform());
            String lang = LocaleContextHolder.getLocale().toString();
            XbbResponse<List<String>> response = new XbbResponse<>();
            try {
                response =  aliyuncallCenterFeignClient.getAliyunCallUserByLoginUserId(aliyunCallCenterListDTO, lang);
                if (!Objects.equals(response.getCode(), ErrorCodeEnum.API_SUCCESS.getCode())) {
                    log.error("调用云呼fegin接口报错:", response.getMsg());
                }else {
                    aliyunCallUserList = response.getResult();
                    if (CollectionsUtil.isEmpty(aliyunCallUserList)) {
                        //代表是云呼那边的超管权限
                        aliyunCallAdminPer = true;
                    }
                }
            }catch (Exception e) {
                log.info("调用云呼fegin接口都没通");
            }
        }
        //老呼叫中心数据权限
        callCallLogListDTO.setUserId(userId);
        List<String> callCenterUserList = callCenterCallLogService.getCallCenterUserListByLoginUser(callCallLogListDTO);
        if (CollectionsUtil.isEmpty(callCenterUserList)) {
            //代表是老呼叫中心的超管权限
            callAdminPer = true;
        }
        //（1）云呼超管以及老呼叫中心超管
        if (aliyunCallAdminPer == true && callAdminPer == true) {
            return;
        }
        BoolQueryBuilder shouldQuery = boolQuery();
        BoolQueryBuilder mustBoolQueryBuilder = boolQuery();
        BoolQueryBuilder callSourceBoolQueryBuilder = boolQuery();
        // (2)云呼超管以及老呼叫中心非超管
        if (aliyunCallAdminPer == true && callAdminPer == false) {
            mustBoolQueryBuilder.must(termQuery("callSource", 0));
            mustBoolQueryBuilder.must(termsQuery("userId.keyword", callCenterUserList));
            callSourceBoolQueryBuilder.filter(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
            shouldQuery.should(mustBoolQueryBuilder);
            shouldQuery.should(callSourceBoolQueryBuilder);
            shouldQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(shouldQuery);
        }else if (aliyunCallAdminPer == false && callAdminPer == true) {
            // (3)云呼非超管以及老呼叫中心超管
            mustBoolQueryBuilder.must(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
            mustBoolQueryBuilder.must(termsQuery("userId.keyword", aliyunCallUserList));
            callSourceBoolQueryBuilder.filter(termQuery("callSource", 0));
            shouldQuery.should(mustBoolQueryBuilder);
            shouldQuery.should(callSourceBoolQueryBuilder);
            shouldQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(shouldQuery);
        }else if (aliyunCallAdminPer == false && callAdminPer == false) {
            //既不是云呼超管也不是老呼叫中心超管
            mustBoolQueryBuilder.must(termQuery("callSource", 0));
            mustBoolQueryBuilder.must(termsQuery("userId.keyword", callCenterUserList));
            BoolQueryBuilder mustBoolQueryBuilderSen = boolQuery();
            mustBoolQueryBuilderSen.must(termsQuery("callSource", CallCenterCallLogCallSourceEnum.listYunCallCallSource()));
            mustBoolQueryBuilderSen.must(termsQuery("userId.keyword", aliyunCallUserList));
            shouldQuery.should(mustBoolQueryBuilder);
            shouldQuery.should(mustBoolQueryBuilderSen);
            shouldQuery.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
            boolQueryBuilder.filter(shouldQuery);
        }


    }

    /**
     * 返回表单共享标识
     *
     * @param corpid 公司id
     * @param formId 表单id
     * @param businessType 业务类型
     * @return true:共享  false:隔离
     */
    private boolean returnFormShareTag(String corpid, Long formId, Integer businessType) throws XbbException {
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = userTeamHelp.getFormShareTag(corpid, formId, businessType);
        return formShareTag;
    }

    /**
     * 获取客户团队的用户id列表
     *
     * @param customerUserEntityList 客户团队实体列表
     * @param loginUserId 登录人的用户id
     * @return
     */
    public List<String> getCustomerUserIdList (List<CustomerUserEntity> customerUserEntityList, String loginUserId) {
        List<String>  userIdStrList = new ArrayList<>();
        userIdStrList.add(loginUserId);
        String teamUserId = "";
        if (CollectionsUtil.isNotEmpty(customerUserEntityList)) {
            for (CustomerUserEntity customerUserEntity : customerUserEntityList) {
                if (Objects.equals(loginUserId, customerUserEntity.getUserId()) && Objects.nonNull(customerUserEntity.getTeamUserId())) {
                    teamUserId = customerUserEntity.getTeamUserId();
                    break;
                }else if (Objects.equals(loginUserId, customerUserEntity.getUserId()) && Objects.isNull(customerUserEntity.getTeamUserId())) {
                    teamUserId = loginUserId;
                    break;
                }
            }
            if (StringUtil.isNotEmpty(teamUserId)) {
                userIdStrList.add(teamUserId);
                for (CustomerUserEntity customerUserEntity : customerUserEntityList) {
                    if (Objects.equals(customerUserEntity.getTeamUserId(), teamUserId)) {
                        userIdStrList.add(customerUserEntity.getUserId());
                    }
                }
            }
        }
        return userIdStrList;
    }

    /**
     * 获取线索团队里面的用户id列表
     *
     * @param clueUserEntities
     * @param loginUserId
     * @return
     */
    public List<String> getClueUserIdList (List<ClueUserEntity> clueUserEntities, String loginUserId) {
        List<String>  userIdStrList = new ArrayList<>();
        userIdStrList.add(loginUserId);
        String teamUserId = "";
        if (CollectionsUtil.isNotEmpty(clueUserEntities)) {
            for (ClueUserEntity clueUserEntity : clueUserEntities) {
                if (Objects.equals(loginUserId, clueUserEntity.getUserId()) && Objects.nonNull(clueUserEntity.getTeamUserId())) {
                    teamUserId = clueUserEntity.getTeamUserId();
                    break;
                }else if (Objects.equals(loginUserId, clueUserEntity.getUserId()) && Objects.isNull(clueUserEntity.getTeamUserId())) {
                    teamUserId = loginUserId;
                    break;
                }
            }
            if (StringUtil.isNotEmpty(teamUserId)) {
                userIdStrList.add(teamUserId);
                for (ClueUserEntity clueUserEntity : clueUserEntities) {
                    if (Objects.equals(clueUserEntity.getTeamUserId(), teamUserId)) {
                        userIdStrList.add(clueUserEntity.getUserId());
                    }
                }
            }
        }
        return userIdStrList;
    }

    /**
     * 获取当前登录人组织架构那边根据数据权限，判断这个数据权限下有哪些人
     *
     * @return
     */
    private List<String> getSysDataPermissionUserList(UserVO userVO, Integer dataPermission) {
        List<String> userIdIn = userModel.getSubIdListByDataPermission(dataPermission, userVO.getUserId(), userVO.getCorpid(), BasicConstant.ONE,false);
        return userIdIn;
    }

    /**
     * 列表页客户、线索界面有个跟进记录查看，这边也需要做数据权限的过滤。
     * （1）登录人员有此跟进记录的数据权限
     * (2) 登录人员为此跟进记录创建人
     *
     * @param formDataListDTO
     */
    public void specialListCustomerCommunicate(FormDataListDTO formDataListDTO, BoolQueryBuilder boolQueryBuilder) throws XbbException{
        String corpid = formDataListDTO.getCorpid();
        Long formId = formDataListDTO.getFormId();
        Integer businessType = formDataListDTO.getBusinessType();
        //表单共享标识，true：共享  false：隔离
        boolean formShareTag = returnFormShareTag(corpid, formId, businessType);
        UserVO userVO = formDataListDTO.getLoginUser();
        String userId = userVO.getUserId();
        UserEntity userEntity = new UserEntity();
        BeanUtil.copyProperties(userVO, userEntity);
        Integer dataPermission = userModel.getDataPermission(userEntity, SaasMarkEnum.SAAS, XbbRefTypeEnum.CUSTOMER_COMMUNICATE.getCode(), 0L);
        if (userVO.isAdminOrBoss() || (Objects.nonNull(dataPermission) && Objects.equals(DataPermissionEnum.ALL.getCode(),dataPermission)) || formShareTag) {
            return;
        }
        //下面就代表是隔离模式
        List<String> finalUserIdList = new ArrayList<>();
        finalUserIdList.add(userId);
        //这部门是我们角色权限的人
        List<String> sysDataPermissionUserList = getSysDataPermissionUserList(userVO, dataPermission);
        if (CollectionsUtil.isNotEmpty(sysDataPermissionUserList)) {
            finalUserIdList.addAll(sysDataPermissionUserList);
        }
        boolQueryBuilder.filter(termsQuery(CustomerCommunicateEnum.CREATOR_ID.getAttr() + ".keyword", finalUserIdList));
    }
}
